import { CurrentUser, Public, RealIp } from '@/decorators';
import {
  PlanCreateDto,
  PlanFindDto,
  PlanListDto,
  PlanLoadDto,
  PlanOrderDto,
  PlanQueryDto,
  PlanRemoveDto,
  PlanRpaImportDto,
  PlanRpaOrderDto,
  PlanUpdateDto,
} from '@/dtos';
import { PlanService } from '@/services/plan.service';
import { halt, ok } from '@/utils';
import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Patch,
  Post,
  Query,
} from '@nestjs/common';
import { Throttle, seconds } from '@nestjs/throttler';
import { BaseController } from './base.controller';

@Controller('plan')
export class PlanController extends BaseController {
  constructor(private readonly planService: PlanService) {
    super();
  }

  @Post('order')
  @Throttle({
    short: {
      ttl: seconds(1),
      limit: 5,
    },
  })
  async order(
    @Body() dto: PlanOrderDto,
    @CurrentUser('id') userId: number,
    @CurrentUser('mobile') mobile: string,
    @RealIp() ip: string,
  ) {
    return ok(await this.planService.order(dto, userId, ip, mobile));
  }

  @Post('list')
  async getList(@Body() dto: PlanListDto) {
    return ok(await this.planService.getList(dto));
  }

  @Get('detail/:id')
  async getDetail(@Param('id') id: number, @CurrentUser('id') userId: number) {
    const { times } = await this.planService.getTimes(id, userId);
    const data = (await this.planService.findOne(
      {
        id,
        isEnabled: true,
      },
      {
        id: true,
        title: true,
        price: true,
        image: true,
        startTime: true,
        endTime: true,
        limit: true,
        perLimit: true,
        isSoldOut: true,
        asset: {
          select: {
            id: true,
            circulation: true,
            image: true,
            desc: true,
            detail: true,
            publisher: {
              select: { id: true, name: true, logo: true, labels: true },
            },
            creator: {
              select: { id: true, name: true, logo: true, labels: true },
            },
            album: {
              select: { id: true, title: true },
            },
          },
        },
      },
    )) as any;
    if (!data) {
      return halt('数据异常');
    }
    const followCount = await this.prisma.userFollowPublisher.count({
      where: {
        publisherId: data.asset.publisher.id,
      },
    });
    const isFollow = await this.prisma.userFollowPublisher.findFirst({
      where: {
        userId,
        publisherId: data.asset.publisher.id,
      },
    });
    return ok({
      ...data,
      price: Number(data.price),
      times,
      followCount,
      isFollow: !!isFollow,
    });
  }

  @Post('admin/query')
  async query(@Body() dto: PlanQueryDto) {
    return ok(await this.planService.query(dto));
  }

  @Post('admin/find')
  async find(@Body() dto: PlanFindDto) {
    return ok(await this.planService.findOne(dto.where, dto.select));
  }

  @Post('admin/create')
  async create(@Body() dto: PlanCreateDto) {
    return ok(await this.planService.create(dto.data));
  }

  @Patch('admin/update')
  async update(@Body() dto: PlanUpdateDto) {
    return ok(await this.planService.update(dto));
  }

  @Delete('admin/remove')
  async remove(@Query() dto: PlanRemoveDto) {
    return ok(await this.planService.remove(dto));
  }

  @Post('admin/load')
  async load(@Body() dto: PlanLoadDto) {
    return ok(await this.planService.load(dto));
  }

  @Public()
  @Post('rpa/order')
  async rpaOrder(@Body() dto: PlanRpaOrderDto) {
    return ok(await this.planService.rpaOrder(dto));
  }

  @Public()
  @Post('rpa/import')
  async rpaImport(@Body() dto: PlanRpaImportDto) {
    return ok(await this.planService.rpaImport(dto));
  }
}
